package ctrFinanceiro.gui;

import java.awt.FontMetrics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.border.BevelBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.DateFormatter;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;

import ctrFinanceiro.bd.ContaBD;
import ctrFinanceiro.bd.MovimentoBD;
import ctrFinanceiro.dmp.Categoria;
import ctrFinanceiro.dmp.Conta;
import ctrFinanceiro.dmp.Movimento;
import ctrFinanceiro.dmp.TipoCategoria;
import ctrFinanceiro.gui.grid.ColumnModelMovimento;
import ctrFinanceiro.gui.grid.TableModelMovimento;
import ctrFinanceiro.utils.Util;

public class MovimentoGUI extends JInternalFrame implements MouseListener {

	private static final long serialVersionUID = 1L;

	private MovimentoBD bd;
	private ContaBD contaBD;

	private JPanel jContentPane = null;

	private JButton jButtonIncluir = null;
	private JButton jButtonAlterar = null;
	private JButton jButtonExcluir = null;
	private JButton jButtonNovo = null;

	private JScrollPane jScrollPaneMovimentos = null;
	private JTable tabela = null;

	private JLabel jLabelIdMovimento = null;
	private JTextField jTextFieldIdMovimento = null;

	private JLabel jLabelContaOrigem = null;
	private JComboBox<Conta> jComboBoxContaOrigem = null;

	private JLabel jLabelContaDestino = null;
	private JComboBox<Conta> jComboBoxContaDestino = null;

	private JLabel jLabelData = null;
	private JFormattedTextField jFormattedTextFieldData = null;

	private JLabel jLabelValor = null;
	private JFormattedTextField jFormattedTextFieldValor = null;

	private JLabel jLabelDocumento = null;
	private JTextField jTextFieldDocumento = null;

	private JLabel jLabelHistorico = null;
	private JTextField jTextFieldHistorico = null;

	private JLabel jLabelObservacao = null;
	private JTextField jTextFieldObservacao = null;

	private JCheckBox jCheckBoxBaixado = null;
	private JCheckBox jCheckBoxTransferencia = null;

	public MovimentoGUI() {
		super("Movimenta\u00E7\u00E3o", false, // resizable
				true, // closable
				false, // maximizable
				true);// iconifiable

		initialize();
	}

	private void initialize() {
		this.bd = new MovimentoBD();
		this.contaBD = new ContaBD();
		this.setSize(739, 440);
		this.setContentPane(getJContentPane());
		this.inicializarComboContaOrigem();
		this.inicializarTabela();
		this.setVisible(true);
	}

	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(null);
			jContentPane.add(getJButtonIncluir(), null);
			jContentPane.add(getJButtonAlterar(), null);
			jContentPane.add(getJButtonExcluir(), null);
			jContentPane.add(getJButtonNovo(), null);

			JPanel panel = new JPanel();
			panel.setBorder(new BevelBorder(BevelBorder.RAISED, null, null,
					null, null));
			panel.setBounds(29, 11, 662, 332);
			panel.setLayout(null);
			jContentPane.add(panel);
			panel.add(getJScrollPaneMovimentos());

			panel.add(getJLabelIdMovimento());
			panel.add(getJTextFieldIdMovimento());

			panel.add(getJLabelContaOrigem());
			panel.add(getJComboBoxContaOrigem());

			panel.add(getJLabelContaDestino());
			panel.add(getJComboBoxContaDestino());

			panel.add(getJLabelData());
			panel.add(getJFormattedTextFieldData());

			panel.add(getJLabelValor());
			panel.add(getJFormattedTextFieldValor());

			panel.add(getJLabelDocumento());
			panel.add(getJTextFieldDocumento());

			panel.add(getJLabelHistorico());

			panel.add(getJTextFieldHistorico());

			panel.add(getJLabelObservacao());
			panel.add(getJTextFieldObservacao());

			panel.add(getJCheckBoxBaixado());
			panel.add(getJCheckBoxTransferencia());
		}
		return jContentPane;
	}

	private JLabel getJLabelIdMovimento() {
		if (jLabelIdMovimento == null) {
			jLabelIdMovimento = new JLabel();
			jLabelIdMovimento.setBounds(10, 157, 26, 16);
			jLabelIdMovimento.setText("Id:");
		}
		return jLabelIdMovimento;
	}

	private JTextField getJTextFieldIdMovimento() {
		if (jTextFieldIdMovimento == null) {
			jTextFieldIdMovimento = new JTextField();
			jTextFieldIdMovimento.setEditable(false);
			jTextFieldIdMovimento.setBounds(new Rectangle(10, 174, 62, 20));
		}
		return jTextFieldIdMovimento;
	}

	private JLabel getJLabelContaOrigem() {
		if (jLabelContaOrigem == null) {
			jLabelContaOrigem = new JLabel("Conta Origem");
			jLabelContaOrigem.setBounds(94, 159, 113, 14);
		}
		return jLabelContaOrigem;
	}

	private JComboBox<Conta> getJComboBoxContaOrigem() {
		if (jComboBoxContaOrigem == null) {
			jComboBoxContaOrigem = new JComboBox<Conta>();
			jComboBoxContaOrigem.setBounds(94, 174, 269, 20);
			jComboBoxContaOrigem.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent e) {
					inicializarComboContaDestino((Conta) jComboBoxContaOrigem
							.getSelectedItem());
				}
			});
			inicializarComboContaDestino((Conta) jComboBoxContaOrigem
					.getSelectedItem());
		}
		return jComboBoxContaOrigem;
	}

	private JLabel getJLabelContaDestino() {
		if (jLabelContaDestino == null) {
			jLabelContaDestino = new JLabel("Conta Destino");
			jLabelContaDestino.setBounds(383, 159, 121, 14);
		}
		return jLabelContaDestino;
	}

	private JComboBox<Conta> getJComboBoxContaDestino() {
		if (jComboBoxContaDestino == null) {
			jComboBoxContaDestino = new JComboBox<Conta>(new ModeloComboBox());
			jComboBoxContaDestino.setBounds(383, 174, 269, 20);
			// jComboBoxUsuario.addItemListener(this);
		}
		return jComboBoxContaDestino;
	}

	private JLabel getJLabelData() {
		if (jLabelData == null) {
			jLabelData = new JLabel("Data");
			jLabelData.setBounds(10, 206, 46, 14);
		}
		return jLabelData;
	}

	private JFormattedTextField getJFormattedTextFieldData() {
		if (jFormattedTextFieldData == null) {
			jFormattedTextFieldData = new JFormattedTextField();
			jFormattedTextFieldData.setHorizontalAlignment(SwingConstants.LEFT);
			jFormattedTextFieldData.setFormatterFactory(new DefaultFormatterFactory(new DateFormatter()));
//			jFormattedTextFieldData.setFormatterFactory(new DefaultFormatterFactory(new DateFormatter()));
			jFormattedTextFieldData.setBounds(10, 219, 150, 20);
		}
		return jFormattedTextFieldData;
	}

	private JLabel getJLabelValor() {
		if (jLabelValor == null) {
			jLabelValor = new JLabel("Valor");
			jLabelValor.setBounds(180, 206, 46, 14);
		}
		return jLabelValor;
	}

	private JFormattedTextField getJFormattedTextFieldValor() {
		if (jFormattedTextFieldValor == null) {
			jFormattedTextFieldValor = new JFormattedTextField();
			jFormattedTextFieldValor.setHorizontalAlignment(SwingConstants.RIGHT);
			jFormattedTextFieldValor.setFormatterFactory(new DefaultFormatterFactory(new NumberFormatter(new DecimalFormat("#,##0.00"))));
			jFormattedTextFieldValor.setBounds(180, 219, 183, 20);
		}
		return jFormattedTextFieldValor;
	}

	private JLabel getJLabelDocumento() {
		if (jLabelDocumento == null) {
			jLabelDocumento = new JLabel();
			jLabelDocumento.setText("Documento");
			jLabelDocumento.setBounds(376, 204, 89, 16);
		}
		return jLabelDocumento;
	}

	private JTextField getJTextFieldDocumento() {
		if (jTextFieldDocumento == null) {
			jTextFieldDocumento = new JTextField();
			jTextFieldDocumento.setBounds(376, 219, 276, 20);

		}
		return jTextFieldDocumento;
	}

	private JLabel getJLabelHistorico() {
		if (jLabelHistorico == null) {
			jLabelHistorico = new JLabel();
			jLabelHistorico.setText("Histórico");
			jLabelHistorico.setBounds(10, 249, 89, 16);
		}
		return jLabelHistorico;
	}

	private JTextField getJTextFieldHistorico() {
		if (jTextFieldHistorico == null) {
			jTextFieldHistorico = new JTextField();
			jTextFieldHistorico.setBounds(10, 264, 317, 20);

		}
		return jTextFieldHistorico;
	}

	private JLabel getJLabelObservacao() {
		if (jLabelObservacao == null) {
			jLabelObservacao = new JLabel();
			jLabelObservacao.setText("Observa\u00E7\u00E3o");
			jLabelObservacao.setBounds(335, 249, 89, 16);
		}
		return jLabelObservacao;
	}

	private JTextField getJTextFieldObservacao() {
		if (jTextFieldObservacao == null) {
			jTextFieldObservacao = new JTextField();
			jTextFieldObservacao.setBounds(335, 264, 317, 20);

		}
		return jTextFieldObservacao;
	}

	private JCheckBox getJCheckBoxBaixado() {
		if (jCheckBoxBaixado == null) {
			jCheckBoxBaixado = new JCheckBox("Baixado");
			jCheckBoxBaixado.setSelected(true);
			jCheckBoxBaixado.setBounds(10, 294, 97, 23);
		}
		return jCheckBoxBaixado;
	}

	private JCheckBox getJCheckBoxTransferencia() {
		if (jCheckBoxTransferencia == null) {
			jCheckBoxTransferencia = new JCheckBox("Transfer\u00EAncia");
			jCheckBoxTransferencia.setSelected(false);
			jCheckBoxTransferencia.setBounds(129, 294, 140, 23);
		}
		return jCheckBoxTransferencia;
	}

	private JScrollPane getJScrollPaneMovimentos() {
		if (jScrollPaneMovimentos == null) {
			jScrollPaneMovimentos = new JScrollPane();
			jScrollPaneMovimentos.setBounds(10, 11, 640, 139);
			jScrollPaneMovimentos.setViewportView(getTabela());
		}
		return jScrollPaneMovimentos;
	}

	private JTable getTabela() {
		if (tabela == null) {
			tabela = new JTable();
		}
		return tabela;
	}

	private JButton getJButtonIncluir() {
		if (jButtonIncluir == null) {
			jButtonIncluir = new JButton();
			jButtonIncluir.setBounds(new Rectangle(64, 358, 102, 24));
			jButtonIncluir.setText("Incluir");
			jButtonIncluir.addMouseListener(this);
		}
		return jButtonIncluir;
	}

	private JButton getJButtonAlterar() {
		if (jButtonAlterar == null) {
			jButtonAlterar = new JButton();
			jButtonAlterar.setBounds(new Rectangle(230, 358, 102, 24));
			jButtonAlterar.setText("Alterar");
			jButtonAlterar.addMouseListener(this);
		}
		return jButtonAlterar;
	}

	private JButton getJButtonExcluir() {
		if (jButtonExcluir == null) {
			jButtonExcluir = new JButton();
			jButtonExcluir.setBounds(new Rectangle(396, 358, 102, 24));
			jButtonExcluir.setText("Excluir");
			jButtonExcluir.addMouseListener(this);
		}
		return jButtonExcluir;
	}

	private JButton getJButtonNovo() {
		if (jButtonNovo == null) {
			jButtonNovo = new JButton();
			jButtonNovo.setBounds(new Rectangle(562, 358, 102, 24));
			jButtonNovo.setText("Novo");
			jButtonNovo.addMouseListener(this);
		}
		return jButtonNovo;
	}

	public void mouseClicked(MouseEvent e) {
		if (e.getSource() == this.getJButtonIncluir()) {
			handlerMovimento("INCLUIR");
		} else if (e.getSource() == this.getJButtonAlterar()) {
			handlerMovimento("ALTERAR");
		} else if (e.getSource() == this.getJButtonExcluir()) {
			handlerMovimento("EXCLUIR");
		} else if (e.getSource() == this.getJButtonNovo()) {
			handlerMovimento("NOVO");
		} else {
			clearFields();
		}
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	public void mousePressed(MouseEvent e) {
	}

	public void mouseReleased(MouseEvent e) {
	}

	private void handlerMovimento(String action) {
		Movimento movimento = new Movimento();

		if (!getJTextFieldIdMovimento().getText().trim().isEmpty()) {
			movimento.setIdMvt(Integer.parseInt(getJTextFieldIdMovimento()
					.getText().trim()));
		}

		movimento.setCtaOrigem((Conta) getJComboBoxContaOrigem().getSelectedItem());
		movimento.setCtaDestino((Conta) getJComboBoxContaDestino().getSelectedItem());
		movimento.setData(Util.parseStringToDate(getJFormattedTextFieldData().getText()));
		movimento.setValor(Util.parseStringToBigDecimal(getJFormattedTextFieldValor().getText()));
		movimento.setDocumento(getJTextFieldDocumento().getText());
		movimento.setHistorico(getJTextFieldHistorico().getText());
		movimento.setObservacao(getJTextFieldObservacao().getText());
		movimento.setBaixado(getJCheckBoxBaixado().isSelected());
		movimento.setTransferencia(getJCheckBoxTransferencia().isSelected());

		if (action.equals("INCLUIR")) {
			bd.addMovimento(movimento);
			clearFields();
		} else if (action.equals("ALTERAR")) {
			bd.updateMovimento(movimento);
			clearFields();
		} else if (action.equals("EXCLUIR")) {
			bd.excludeMovimento(movimento);
			clearFields();
		} else if (action.equals("NOVO"))
			clearFields();
		inicializarTabela();
	}

	private void clearFields() {
		getJTextFieldIdMovimento().setText("");
		getJFormattedTextFieldData().setText("");
		getJFormattedTextFieldValor().setText("");
		getJTextFieldDocumento().setText("");
		getJTextFieldHistorico().setText("");
		getJTextFieldObservacao().setText("");
		getJCheckBoxBaixado().setSelected(true);
		getJCheckBoxTransferencia().setSelected(false);
		getJComboBoxContaDestino().setSelectedItem(null);
		getJComboBoxContaOrigem().setSelectedItem(null);
	}

	private void inicializarComboContaOrigem() {
		List<Conta> contasOrigem = contaBD.getContas();
		for (Conta conta : contasOrigem) {
			jComboBoxContaOrigem.addItem(conta);
		}
	}

	private void inicializarComboContaDestino(Conta contaOrigem) {
		
		List<Conta> contasDestino = null;

		if (null != contaOrigem) {

			if (contaOrigem.getCategoria().getTipo().equals(TipoCategoria.C)) {
				contasDestino = contaBD.getContasPorTipoCategoria(
						TipoCategoria.D, TipoCategoria.R);
			} else {
				contasDestino = contaBD
						.getContasPorTipoCategoria(TipoCategoria.C);
			}
			ModeloComboBox model = (ModeloComboBox)getJComboBoxContaDestino().getModel();
			model.addAll(contasDestino);

		}
	}

	private void inicializarTabela() {
		tabela.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		tabela.setModel(new TableModelMovimento(bd.getMovimentos()));

		// ajuda a identificar a tabela no listner
		tabela.setSelectionModel(new DefaultListSelectionModel() {

			private static final long serialVersionUID = 1L;

			public String toString() {
				return "tabela";
			}
		});
		tabela.getSelectionModel().addListSelectionListener(
				new MyTableListener());
		tabela.setAutoCreateColumnsFromModel(false);
		FontMetrics fm = tabela.getFontMetrics(tabela.getFont());
		tabela.setColumnModel(new ColumnModelMovimento(fm));
		tabela.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

	}

	private class MyTableListener implements ListSelectionListener {

		public void valueChanged(ListSelectionEvent e) {

			ListSelectionModel lsm = (ListSelectionModel) e.getSource();

			// Returns true if this is one of multiple change events.
			if (e.getValueIsAdjusting())
				return;

			if (!(lsm.isSelectionEmpty())) {

				if (e.getSource().toString().equals("tabela")) {

					int sr = tabela.getSelectedRow();
					Movimento movimento = ((TableModelMovimento) tabela
							.getModel()).getValues(sr);

					jTextFieldIdMovimento.setText(String.valueOf(movimento.getIdMvt()));
					
					DefaultComboBoxModel<Conta> comboBoxModel = (DefaultComboBoxModel<Conta>) jComboBoxContaOrigem.getModel();
					comboBoxModel.setSelectedItem(movimento.getCtaOrigem());

//					jComboBoxContaOrigem.setSelectedItem(movimento.getCtaOrigem());
	
					ModeloComboBox comboBoxContaDestino = (ModeloComboBox) jComboBoxContaDestino.getModel();
					comboBoxContaDestino.setSelectedItem(movimento.getCtaDestino());
					
//					jComboBoxContaDestino.setSelectedItem(movimento.getCtaDestino());
					jFormattedTextFieldData.setText(Util.parseDateToString(movimento.getData()));
					jFormattedTextFieldValor.setText(Util.parseBigDecimalToString(movimento.getValor()));
					jTextFieldDocumento.setText(movimento.getDocumento());
					jTextFieldHistorico.setText(movimento.getHistorico());
					jTextFieldObservacao.setText(movimento.getObservacao());
					jCheckBoxTransferencia.setSelected(movimento.getTransferencia());
					jCheckBoxBaixado.setSelected(movimento.getBaixado());
				}
			}
		}
	}
	
	/**
	 * Classe interna responsável por gerenciar a comboBox de Conta Destino.
	 * @author Gabriel
	 * @since 19/10/2010
	 * @version 1.0
	 */
	private class ModeloComboBox extends AbstractListModel<Conta> implements ComboBoxModel<Conta>{
		private static final long serialVersionUID = -5909856485211809081L;
		
		// Lista que representa os dados da comboBox
		List<Conta> dados = new ArrayList<Conta>();
		
		// Atributo onde será armazenado o valor do item selecionado na comboBox.
		Conta selecionado = null;
				
		
		public Conta getElementAt(int index) {
			return dados.get(index);
		}	

		public int getSize() {
			return dados.size();
		}
		
		public void setSelectedItem(Object  conta){				
			selecionado = (Conta) conta;						
		}
		
		public Object getSelectedItem(){
			if(selecionado == null && dados.size() > 0){
				selecionado = dados.get(0);
			}
			return selecionado;
		}	
		
		/**
		 * Método responsável por adicionar valores na comboBox.
		 * @param String[] listaDados - Dados a serem adicionados.
		 */
		public void addAll(List<Conta> listaDados) {
			this.dados.clear();
			setSelectedItem(null);
			
			for(Conta dado : listaDados){
				// Adicionando na comboBox item por item.
				this.dados.add(dado);
				//Atualiza o visual da comboBox a cada item adicionado.
				fireIntervalAdded(dado, 0, 0);
			}
			
		}
	}
	
}
